﻿/*
* 创建者：LIYINFAI
* 创建时间：2023/7/17 11:38:24
* 描述：
* --------------------------------------
* 修改说明：
* --------------------------------------
*/
using System;
using System.ComponentModel;
using System.Drawing.Drawing2D;
using System.Drawing;
using System.Windows.Forms;
using CommonLibrary.Forms;
using System.Reflection;

namespace CommonLibrary
{
    /// <summary>
    /// 窗体标签控件
    /// </summary>
    public class FormTabControl : TabControl
    {
        /// <summary>
        /// 构造函数
        /// </summary>
        public FormTabControl()
            : base()
        {
            this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            this.SetStyle(ControlStyles.DoubleBuffer, true);
            this.SetStyle(ControlStyles.ResizeRedraw, true);
            this.SetStyle(ControlStyles.Selectable, true);
            this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
            this.SetStyle(ControlStyles.UserPaint, true);
            MethodInfo method = base.GetType().GetMethod("SetStyle", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.InvokeMethod);
            method.Invoke(this, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, new object[]
            {
                ControlStyles.Selectable,
                false
            }, Application.CurrentCulture);
            this.ItemSize = new Size(this.ItemSize.Width, 40);
            this.Appearance = TabAppearance.FlatButtons;
        }
        private Color _backColor = Color.White;
        /// <summary>
        /// 背景颜色
        /// </summary>
        [Browsable(true)]
        [EditorBrowsable(EditorBrowsableState.Always)]
        [DefaultValue(typeof(Color), "WhiteSmoke")]
        public override Color BackColor
        {
            get { return _backColor; }
            set
            {
                _backColor = value;
                base.Invalidate(true);
            }
        }
        private Color _borderColor = Color.FromArgb(232, 232, 232);
        /// <summary>
        /// 边框颜色
        /// </summary>
        [DefaultValue(typeof(Color), "232, 232, 232")]
        [Description("TabContorl边框色")]
        public Color BorderColor
        {
            get { return _borderColor; }
            set
            {
                _borderColor = value;
                base.Invalidate(true);
            }
        }
        private Color _headSelectedForeColor = ColorSettings.TabHeaderSelectedForeColor;
        /// <summary>
        /// 头部选中后的前景颜色
        /// </summary>
        [DefaultValue(typeof(Color), "White")]
        [Description("TabPage头部选中后的前景颜色")]
        public Color HeadSelectedForeColor
        {
            get { return _headSelectedForeColor; }
            set { _headSelectedForeColor = value; }
        }
        private Color _headSelectedBackColor = ColorSettings.TabHeaderSelectedBackColor;
        /// <summary>
        /// 头部选中后的背景颜色
        /// </summary>
        [DefaultValue(typeof(Color), "30,56,83")]
        [Description("TabPage头部选中后的背景颜色")]
        public Color HeadSelectedBackColor
        {
            get { return _headSelectedBackColor; }
            set { _headSelectedBackColor = value; }
        }
        private Color _headerBackColor = ColorSettings.TabHeaderDefaultBackColor;
        /// <summary>
        /// 头部默认背景颜色
        /// </summary>
        [DefaultValue(typeof(Color), "WhiteSmoke")]
        [Description("TabPage头部默认背景颜色")]
        public Color HeaderBackColor
        {
            get { return _headerBackColor; }
            set { _headerBackColor = value; }
        }
        private Font _headerFont = new Font("微软雅黑", 9, FontStyle.Bold);
        /// <summary>
        /// 头部字体
        /// </summary>
        [Description("TabPage头部字体")]
        public Font HeaderFont
        {
            get { return _headerFont; }
            set { _headerFont = value; }
        }
        /// <summary>
        /// 初始化
        /// </summary>
        /// <param name="args"></param>
        public void Init(params Form[] args)
        {
            this.TabPages.Clear();
            if (args != null && args.Length > 0)
            {
                foreach (Form form in args)
                {
                    TabPage tabPage = new TabPage();
                    form.FormBorderStyle = FormBorderStyle.None;
                    form.TopLevel = false;
                    form.Visible = true;
                    form.Dock = DockStyle.Fill;
                    if (form is HWFrmWithTitle)
                    {
                        (form as HWFrmWithTitle).IsTitleShown = false;
                    }
                    tabPage.Text = form.Text;
                    tabPage.Controls.Add(form);
                    AddTabPage(tabPage);
                }
            }
        }
        private void AddTabPage(TabPage tabPage)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new Action(() =>
                {
                    AddTabPage(tabPage);
                }));
            }
            else
            {
                this.TabPages.Add(tabPage);
                Application.DoEvents();
            }
        }
        /// <summary>
        /// 绘制背景
        /// </summary>
        /// <param name="g"></param>
        /// <param name="clipRect"></param>
        protected void PaintTransparentBackground(Graphics g, Rectangle clipRect)
        {
            if ((this.Parent != null))
            {
                clipRect.Offset(this.Location);
                PaintEventArgs e = new PaintEventArgs(g, clipRect);
                GraphicsState state = g.Save();
                g.SmoothingMode = SmoothingMode.HighSpeed;
                try
                {
                    g.TranslateTransform((float)-this.Location.X, (float)-this.Location.Y);
                    this.InvokePaintBackground(this.Parent, e);
                    this.InvokePaint(this.Parent, e);
                }
                finally
                {
                    g.Restore(state);
                    clipRect.Offset(-this.Location.X, -this.Location.Y);
                    //新加片段,待测试
                    using (SolidBrush brush = new SolidBrush(_backColor))
                    {
                        clipRect.Inflate(1, 1);
                        g.FillRectangle(brush, clipRect);
                    }
                }
            }
            else
            {
                System.Drawing.Drawing2D.LinearGradientBrush backBrush = new System.Drawing.Drawing2D.LinearGradientBrush(this.Bounds, SystemColors.ControlLightLight, SystemColors.ControlLight, System.Drawing.Drawing2D.LinearGradientMode.Vertical);
                g.FillRectangle(backBrush, this.Bounds);
                backBrush.Dispose();
            }
        }
        private void PaintAllTheTabs(System.Windows.Forms.PaintEventArgs e)
        {
            if (this.TabCount > 0)
            {
                for (int index = 0; index < this.TabCount; index++)
                {
                    this.PaintTab(e, index);
                }
            }
        }
        private void PaintTab(System.Windows.Forms.PaintEventArgs e, int index)
        {
            GraphicsPath path = this.GetTabPath(index);
            this.PaintTabBackground(e.Graphics, index, path);
            this.PaintTabBorder(e.Graphics, index, path);
            this.PaintTabText(e.Graphics, index);
            this.PaintTabImage(e.Graphics, index);
        }
        /// <summary>
        /// 设置选项卡头部颜色
        /// </summary>
        /// <param name="graph">The graph.</param>
        /// <param name="index">The index.</param>
        /// <param name="path">The path.</param>
        private void PaintTabBackground(System.Drawing.Graphics graph, int index, System.Drawing.Drawing2D.GraphicsPath path)
        {
            Rectangle rect = this.GetTabRect(index);
            if (rect.Width == 0 || rect.Height == 0) return;
            System.Drawing.Brush buttonBrush = new System.Drawing.Drawing2D.LinearGradientBrush(rect, _headerBackColor, _headerBackColor, LinearGradientMode.Vertical);  //非选中时候的 TabPage 页头部背景色
            graph.FillPath(buttonBrush, path);
            buttonBrush.Dispose();
        }
        /// <summary>
        /// 设置选项卡头部边框色
        /// </summary>
        /// <param name="graph">The graph.</param>
        /// <param name="index">The index.</param>
        /// <param name="path">The path.</param>
        private void PaintTabBorder(System.Drawing.Graphics graph, int index, System.Drawing.Drawing2D.GraphicsPath path)
        {
            Pen borderPen = new Pen(_borderColor);// TabPage 非选中时候的 TabPage 头部边框色
            graph.DrawPath(borderPen, path);
            borderPen.Dispose();
        }
        private void PaintTabImage(System.Drawing.Graphics g, int index)
        {
            Image tabImage = null;
            if (this.TabPages[index].ImageIndex > -1 && this.ImageList != null)
            {
                tabImage = this.ImageList.Images[this.TabPages[index].ImageIndex];
            }
            else if (this.TabPages[index].ImageKey.Trim().Length > 0 && this.ImageList != null)
            {
                tabImage = this.ImageList.Images[this.TabPages[index].ImageKey];
            }
            if (tabImage != null)
            {
                Rectangle rect = this.GetTabRect(index);
                g.DrawImage(tabImage, rect.Right - rect.Height - 4, 4, rect.Height - 2, rect.Height - 2);
            }
        }
        private void PaintTabText(System.Drawing.Graphics graph, int index)
        {
            string tabtext = this.TabPages[index].Text;
            System.Drawing.StringFormat format = new System.Drawing.StringFormat();
            format.Alignment = StringAlignment.Near;
            format.LineAlignment = StringAlignment.Center;
            format.Trimming = StringTrimming.EllipsisCharacter;
            Brush forebrush = null;
            if (this.TabPages[index].Enabled == false)
            {
                forebrush = SystemBrushes.ControlDark;
            }
            else
            {
                forebrush = SystemBrushes.ControlText;
            }
            Font tabFont = this.HeaderFont;
            if (index == this.SelectedIndex)
            {
                if (this.TabPages[index].Enabled != false)
                {
                    forebrush = new SolidBrush(_headSelectedForeColor);
                }
            }
            Rectangle rect = this.GetTabRect(index);
            var txtSize = ControlHelper.GetStringWidth(tabtext, graph, tabFont);
            Rectangle rect2 = new Rectangle(rect.Left + (rect.Width - txtSize) / 2 - 1, rect.Top, rect.Width, rect.Height);
            graph.DrawString(tabtext, tabFont, forebrush, rect2, format);
        }

        /// <summary>
        /// 设置 TabPage 内容页边框色
        /// </summary>
        /// <param name="e">The <see cref="System.Windows.Forms.PaintEventArgs" /> instance containing the event data.</param>
        private void PaintTheTabPageBorder(System.Windows.Forms.PaintEventArgs e)
        {
            if (this.TabCount > 0)
            {
                Rectangle borderRect = this.TabPages[0].Bounds;
                //borderRect.Inflate(1, 1);
                Rectangle rect = new Rectangle(borderRect.X - 2, borderRect.Y - 1, borderRect.Width + 5, borderRect.Height + 2);
                ControlPaint.DrawBorder(e.Graphics, rect, this.BorderColor, ButtonBorderStyle.Solid);
            }
        }
        private void PaintTheSelectedTab(System.Windows.Forms.PaintEventArgs e)
        {
            if (this.SelectedIndex == -1 || this.SelectedIndex >= this.TabCount)
                return;
            Rectangle selrect;
            selrect = this.GetTabRect(this.SelectedIndex);
            e.Graphics.FillRectangle(new SolidBrush(_headSelectedBackColor), selrect);
            System.Drawing.StringFormat format = new System.Drawing.StringFormat();
            format.Alignment = StringAlignment.Near;
            format.LineAlignment = StringAlignment.Center;
            format.Trimming = StringTrimming.EllipsisCharacter;
            Brush forebrush = new SolidBrush(_headSelectedForeColor);
            Font tabFont = this.HeaderFont;
            string tabtext = this.TabPages[this.SelectedIndex].Text;
            var txtSize = ControlHelper.GetStringWidth(tabtext, e.Graphics, tabFont);
            Rectangle rect2 = new Rectangle(selrect.Left + (selrect.Width - txtSize) / 2 - 1,
                selrect.Top, selrect.Width, selrect.Height);
            e.Graphics.DrawString(tabtext, tabFont, forebrush, rect2, format);
        }
        private GraphicsPath GetTabPath(int index)
        {
            System.Drawing.Drawing2D.GraphicsPath path = new System.Drawing.Drawing2D.GraphicsPath();
            path.Reset();
            Rectangle rect = this.GetTabRect(index);
            switch (Alignment)
            {
                case TabAlignment.Top:
                    break;
                case TabAlignment.Bottom:
                    break;
                case TabAlignment.Left:
                    break;
                case TabAlignment.Right:
                    break;
            }
            path.AddLine(rect.Left, rect.Top, rect.Left, rect.Bottom);
            path.AddLine(rect.Left, rect.Top, rect.Right, rect.Top);
            path.AddLine(rect.Right, rect.Top, rect.Right, rect.Bottom);
            path.AddLine(rect.Right, rect.Bottom, rect.Left, rect.Bottom);
            return path;
        }
        /// <summary>
        /// 绘制
        /// </summary>
        /// <param name="e"></param>
        protected override void OnPaint(PaintEventArgs e)
        {
            // Paint the Background 
            base.OnPaint(e);
            this.PaintTransparentBackground(e.Graphics, this.ClientRectangle);
            this.PaintAllTheTabs(e);
            this.PaintTheTabPageBorder(e);
            this.PaintTheSelectedTab(e);
        }
    }
}
